using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using SubversionReports.Utilities;

namespace SubversionReports.Web.Controls
{
    public partial class DiffView : UserControl
    {
        private string path;
        private int revisionA;
        private int revisionB;
        

        /// <summary>
        /// Gets or sets the path.
        /// </summary>
        /// <value>The path.</value>
        public string Path
        {
            get { return Request["Path"] ?? path; }
            set { path = value; }
        }

        /// <summary>
        /// Gets or sets the revision A.
        /// </summary>
        /// <value>The revision A.</value>
        public int RevisionA
        {
            get
            {
                if (Request["CompareTo"] != null)
                    int.TryParse(Request["CompareTo"], out revisionA);
                return revisionA;
            }
            set { revisionA = value; }
        }

        /// <summary>
        /// Gets or sets the revision B.
        /// </summary>
        /// <value>The revision B.</value>
        public int RevisionB
        {
            get
            {
                if (Request["RevisionId"] != null)
                    int.TryParse(Request["RevisionId"], out revisionB);
                return revisionB;
            }
            set { revisionB = value; }
        }

        /// <summary>
        /// Handles the Load event of the Page control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if(SvnWebDav.AuthenticationSuceeded
                && Visible
                && !string.IsNullOrEmpty(Path)
                && RevisionA > 0
                && RevisionB > 0)
            {
                string textA = SvnWebDav.GetFileRevisionFromWebDav(SvnWebDav.CurrentRepositoryRootUrl, SvnWebDav.CurrentRepositoryUsername, SvnWebDav.CurrentRepositoryPassword, RevisionA, Path);
                string textB = SvnWebDav.GetFileRevisionFromWebDav(SvnWebDav.CurrentRepositoryRootUrl, SvnWebDav.CurrentRepositoryUsername, SvnWebDav.CurrentRepositoryPassword, RevisionB, Path);

                string[] aLines = textA.Split('\n');
                string[] bLines = textB.Split('\n');
                int n = 0;
                List<FileLine> fileLines = new List<FileLine>();
                foreach (Diff.Item difference in Diff.DiffText(textA, textB, true, true, false))
                {
                    // write unchanged lines
                    while ((n < difference.StartB) && (n < bLines.Length))
                    {
                        fileLines.Add(new FileLine((n + 1).ToString(), HttpUtility.HtmlEncode(bLines[n]), null));
                        n++;
                    }

                    // write deleted lines
                    for (int m = 0; m < difference.DeletedA; m++)
                    {
                        fileLines.Add(new FileLine("&nbsp;", HttpUtility.HtmlEncode(aLines[difference.StartA + m]), "d"));
                    }

                    // write inserted lines
                    while (n < difference.StartB + difference.InsertedB)
                    {
                        fileLines.Add(new FileLine((n + 1).ToString(), HttpUtility.HtmlEncode(bLines[n]), "i"));
                        n++;
                    }

                    // write rest of unchanged lines
                    while (n < bLines.Length)
                    {
                        fileLines.Add(new FileLine((n + 1).ToString(), HttpUtility.HtmlEncode(bLines[n]), null));
                        n++;
                    }
                }
                DiffGridView.DataSource = fileLines;
                DiffGridView.DataBind();
            }
        }

        internal class FileLine
        {
            private string number;
            private string text;
            private string cssClass;

            /// <summary>
            /// Gets or sets the number.
            /// </summary>
            /// <value>The number.</value>
            public string Number
            {
                get { return number; }
                set { number = value; }
            }

            /// <summary>
            /// Gets or sets the text.
            /// </summary>
            /// <value>The text.</value>
            public string Text
            {
                get { return text; }
                set { text = value; }
            }

            public string CssClass
            {
                get { return cssClass; }
                set { cssClass = value; }
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="FileLine"/> class.
            /// </summary>
            /// <param name="number">The number.</param>
            /// <param name="text">The text.</param>
            /// <param name="cssClass">The CSS class.</param>
            public FileLine(string number, string text, string cssClass)
            {
                this.number = number;
                this.text = text;
                this.cssClass = cssClass;
            }
        }
    }
}